﻿using System;
using System.ComponentModel;
using System.Xml.Serialization;
using Microsoft.WowAddonStudio.FrameXml.Serialization.Attributes;
using Microsoft.WowAddonStudio.FrameXml.Serialization.Enumerations;
using Microsoft.WowAddonStudio.FrameXml.Serialization.TypeConverters;

namespace Microsoft.WowAddonStudio.FrameXml.Serialization.LayoutFrames
{
    [Serializable]
    [DesignerCategory("code")]
    [XmlType(Namespace = "http://www.blizzard.com/wow/ui/")]
    [XmlRoot(Namespace = "http://www.blizzard.com/wow/ui/", IsNullable = false)]
    [TypeConverter(typeof(TextureExpandableObjectConverter))]
    public class Texture : LayeredLayoutFrame, ICloneable, ICopiable<Texture>, IEquatable<Texture>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="Texture"/> class.
        /// </summary>
        public Texture() : base(DrawLayer.Artwork)
        {

        }

        /// <summary>
        /// Gets or sets the file the texture shows.
        /// </summary>
        [XmlAttribute("file")]
        [Category("Appearance")]
        [File(FileType.Image)]
        [NotifyParentProperty(true)]
        [Description("This refers to a file used by element, path is relative to scheme path: if addon is in \"MyAddon\" folder file specified \"myfile.lua\" will be searched in this folder (i guess only, needs testing). \"\\Interface\\Wherever\" seems to be the same as \"Interface\\Wherever\" (\"C:\\{{WoW}}\\Interface\\Wherever\").")]
        public string File
        {
            get { return Properties.GetValue<string>("File"); }
            set { Properties.SetValue("File", value); }
        }

        /// <summary>
        /// Gets or sets the alpha mode of the texture.
        /// </summary>
        [XmlAttribute("alphaMode")]
        [DefaultValue(AlphaMode.Blend)]
        [Category("Appearance")]
        [NotifyParentProperty(true)]
        [Description("Defines a way transparency applied.")]
        public AlphaMode AlphaMode
        {
            get { return Properties.GetValue<AlphaMode>("AlphaMode"); }
            set { Properties.SetValue("AlphaMode", value); }
        }

        /// <summary>
        /// Gets or sets the texture coordinates of the texture.
        /// </summary>
        [XmlElement]
        [Category("Layout")]
        [NotifyParentProperty(true)]
        [Description("Determines how much of the specified texture is to be shown. There are four specifications: \"left\", \"right\", \"top\", and \"bottom\". Each one specifies the coordinates of what the image should show, using a scale value.")]
        public TexCoords TexCoords
        {
            get { return Properties.GetValue<TexCoords>("TexCoords"); }
            set { Properties.SetValue("TexCoords", value); }
        }

        /// <summary>
        /// Gets or sets the color of the texture.
        /// </summary>
        [XmlElement]
        [Category("Appearance")]
        [EditorBrowsable]
        [NotifyParentProperty(true)]
        [Description("The color used to display texture.")]
        [Color]
        public Color Color
        {
            get { return Properties.GetValue<Color>("Color"); }
            set { Properties.SetValue("Color", value); }
        }

        /// <summary>
        /// Gets a value indicating whether a serialization object is complete and can be rendered.
        /// </summary>
        /// <value></value>
        public override bool IsComplete
        {
            get
            {
                return !String.IsNullOrEmpty(File) || !(Color == null);
            }
        }

        /// <summary>
        /// Creates a new object that is a copy of the instance.
        /// </summary>
        /// <returns>The copied instance.</returns>
        /// <remarks>Performs a deep copy.</remarks>
        public new Texture Copy()
        {
            return new Texture
                       {
                           AlphaMode = AlphaMode,
                           Color = Color != null ? Color.Copy() : null,
                           DrawLayer = DrawLayer,
                           File = File,
                           Hidden = Hidden,
                           Inherits = Inherits,
                           Name = Name,
                           ParentFrame = ParentFrame,
                           SetAllPoints = SetAllPoints,
                           SizeDimension = SizeDimension != null ? SizeDimension.Copy() : null,
                           TexCoords = TexCoords != null ? TexCoords.Copy() : null,
                           Virtual = Virtual
                       };
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public new object Clone()
        {
            return Copy();
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <param name="other">An object to compare with this object.</param>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        public bool Equals(Texture other)
        {
            if (other == this)
                return true;
            if (other == null)
                return false;

            return Object.Equals(this.AlphaMode, other.AlphaMode) &&
                   Object.Equals(this.Color, other.Color) &&
                   Object.Equals(this.DrawLayer, other.DrawLayer) &&
                   Object.Equals(this.File, other.File) &&
                   Object.Equals(this.Hidden, other.Hidden) &&
                   Object.Equals(this.Inherits, other.Inherits) &&
                   Object.Equals(this.Name, other.Name) &&
                   Object.Equals(this.ParentFrame, other.ParentFrame) &&
                   Object.Equals(this.SetAllPoints, other.SetAllPoints) &&
                   Object.Equals(this.SizeDimension, other.SizeDimension) &&
                   Object.Equals(this.TexCoords, other.TexCoords) &&
                   Object.Equals(this.Virtual, other.Virtual);
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <exception cref="T:System.NullReferenceException">
        /// The <paramref name="obj"/> parameter is null.
        /// </exception>
        public override bool Equals(object obj)
        {
            return (this.Equals(obj as Texture));
        }

        /// <summary>
        /// Serves as a hash function for a particular type.
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        public override int GetHashCode()
        {
            return this.Name != null ? this.Name.GetHashCode() : 0;
        }
    }
}